function linkState(component, storeName = 'fields', defaultStates = {}) {
  if (process.env.NODE_ENV !== 'production') {
    console.error('LinkState is no longer recommended, use the form component replacement.'); // eslint-disable-line
  }
  if (!component || typeof component.setState !== 'function') {
    throw new Error("Can't resolve setState function.");
  }

  /* eslint-disable no-param-reassign */
  component.state = component.state || {};
  component.state[storeName] = Object.assign({}, component.state[storeName], defaultStates);
  /* eslint-enable no-param-reassign */

  function getState(fieldName, defaultValue) {
    const value = component.state[storeName][fieldName];
    return value !== undefined ? value : defaultValue;
  }

  function setState(fieldName, updater, defaultValue) {
    component.setState(state => ({
      ...state,
      [storeName]: {
        ...state[storeName],
        [fieldName]: (typeof updater === 'function'
          ? updater(state[storeName][fieldName] || defaultValue)
          : updater),
      },
    }));
  }

  function linkValue(fieldName) {
    return {
      value: getState(fieldName),
      onChange: (e) => {
        const value = (e && e.target) ? e.target.value : e;
        setState(fieldName, value);
      },
    };
  }

  function linkRadio(fieldName, value) {
    return {
      checked: getState(fieldName) === value,
      onChange: () => {
        setState(fieldName, value);
      },
    };
  }

  function linkCheckbox(fieldName, value) {
    return {
      checked: getState(fieldName, []).includes(value),
      onChange: (e) => {
        const checked = (e && e.target) ? e.target.checked : e;
        setState(
          fieldName,
          (state) => (checked ? [...state, value] : state.filter(x => x !== value)),
          []
        );
      },
    };
  }

  return (fieldName, value, type) => {
    switch (type) {
      case 'checkbox':
        return linkCheckbox(fieldName, value);
      case 'radio':
        return linkRadio(fieldName, value);
      default:
        return linkValue(fieldName);
    }
  };
}

export default linkState;
